/* Printer status information */
/** @file
     */
/* Created 07.11.2004 T. Milius
   Changed 17.10.2005 T. Milius */
/* (c) Copyright 2004-2005 by Thomas Milius Stade, Germany
   Source must not be altered without agreement of the owner.
   The owner of the source is allowed to use this code inside programs without
   publishing the code of this programs. These programs may be commercial.
   Other developers can use this source freely inside own software if the source
   code of this programs is made public to same conditions like valid to this code
   and no commercial profit is taken from the programs based on this code

   Code or parts of it are not allowed to be used within GPL code or
   similar licenses which are "infecting" other code and trying to "supersede"
   other licenses. */
/** @mainpage
    @author Thomas Milius Stade, Germany
    @version 1.08
    @date 2004-2007

    PrtInfo provides simple actions on printers, like
    eg cleaning of printheads, changing of cartridges etc.
    and displaying of cartridge ink levels. This is done
    independently of the printing process.

    Beschreibe Ablauf  */
/* RISCOS */

/* !!!!!!!!!! libraries !!!!!!!!!! */
/* ---------- ANSI-C ---------- */
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>

/* ------------ RISC OS ------------ */
#include <kernel.h>
#include <swis.h>

/* ------------ Toolbox ------------ */
#include <event.h>
#include <toolbox.h>
#include <wimp.h>
#include <wimplib.h>
#include <menu.h>
#include <gadgets.h>
#include <iconbar.h>
#include <window.h>
#include <drawfile.h>

/* ------------ own ------------ */
#include "common.h"
#include "settings.h"
#include "tb_defs.h"
#include "network.h"
#include "printeractions.h"
#include "communication.h"
#include "cartrinfo.h"
#include "printers.h"

/* !!!!!!!!!!! definitions !!!!!!!!!! */
#define EVENT_NOT_CLAIMED 0
#define EVENT_CLAIMED     1

#define CHOICES_PATH "<Choices$Dir>.PrtInfo"
#define RESOURCES_PATH   "<PrtInfo$Dir>.Resources"
#define COMMANDS_SUBPATH ".Commands"
#define TRACE_PATH  "<Wimp$ScrapDir>.PrtInfo"

/* internal Errors range from 0x70 ownwards */
#define ERROR_MEMORY_ALLOCATION_WINDOW   128
#define ERROR_PRINTER_DETERMINATION      129
#define ERROR_CONNECTION_DETERMINATION   130
#define ERROR_PRINTER_ALIAS_FILE         131
#define ERROR_PRINTER_TYPE               132
#define ERROR_PRINTER_TYPE_ALIAS_FILE    133
#define ERROR_MEMORY_CONTROL_FILE_NAME   134
#define ERROR_NO_DIALOGUE_BUTTON_SET     135
#define ERROR_CARTRIDGE_INFORMATION_FILE 136
#define ERROR_CANT_OPEN_TRACE_FILE       137
#define ERROR_PRINTERS_NOT_RUNNING       138

#define MAX_CARTRIDGE_MANUFACTURERS 10

/* !!!!!!!!!! data structures !!!!!!!!!! */
struct status_struct {
struct status_struct *previous_status;
struct status_struct *next_status;
ObjectId window;
ObjectId main_menu;
bool lock_input;
char cartridge_manufacturer[MAX_CARTRIDGE_MANUFACTURERS][MAX_MESSAGE_LENGTH];
int component_counter;
int actual_cartridge_manufacturer;
struct information_struct information;
};

/* ---------- RISCOS Wimp Toolbox Communication ---------- */
MessagesFD    messages;
IdBlock       id_block;

_kernel_oserror app_error;

/* !!!!!!!!!! support functions !!!!!!!!!! */
bool show_message(int message_number,
                  FILE *trace,
                  ...)
{
va_list args;
char message_token[20];
char format[200];
_kernel_swi_regs regs;

sprintf(message_token,
        "Error_%d",
        message_number);
regs.r[0]=(int) messages.data;
regs.r[1]=(int) message_token;
regs.r[2]=(int) format;
regs.r[3]=199;
regs.r[4]=0;
regs.r[5]=0;
regs.r[6]=0;
regs.r[7]=0;
_kernel_swi(MessageTrans_Lookup, &regs, &regs);
va_start(args, trace);
vsprintf(app_error.errmess, format, args);
va_end(args);
if (trace) {
  fprintf(trace,
          "Error: %s\n",
          app_error.errmess);
  }
app_error.errnum=0;
wimp_report_error(&app_error,
                  0,
                  0,
                  APPLICATION_NAME,
                  0,
                  0);
return true;
}

extern bool drop_application(void);

void application_report_error(_kernel_oserror *error_os,
                              bool drop_application_flag)
{

wimp_report_error(error_os,
                  0,
                  APPLICATION_NAME,
                  0,
                  0,
                  0);
if (drop_application_flag) {
  drop_application();
  }
exit(EXIT_FAILURE);
}

bool search_printer_alias_file(struct information_struct *information,
                               char *file_name,
                               bool *loop_flag)
{
char *c;
char input_line[MAX_STRING_LENGTH];
char actual_printer_name[MAX_MESSAGE_LENGTH];
FILE *info_file;

if (!(info_file=fopen(file_name, "r"))) return false;
input_line[MAX_STRING_LENGTH - 1]='\0';
while ((!feof(info_file))) {
  strcpy(input_line, "");
  fgets(input_line, MAX_STRING_LENGTH - 1, info_file);
  if (!feof(info_file)) {
    c=&input_line[strlen(input_line) - 1];
    while ((c >= input_line) &&
           ((*c == '\n') ||
            (isspace(*c)))) {
      *c='\0';
      c--;
      }
    if (input_line[0] != '#') {
      /* No comment. Real data */
      if (sscanf(input_line,
                 "%[^,],%[^,],%[^,]",
                 actual_printer_name,
                 information->general_variables.manufacturer,
                 information->general_variables.printer_type) == 3) {
        if (strcmp(actual_printer_name, information->printer->printer_name) == 0) {
          fclose(info_file);
          *loop_flag=false;
          return true;
          }
        }
      }
    }
  }
fclose(info_file);
return true;
}

bool register_action(struct status_struct *actual_status,
                     int action,
                     int sub_selection)
{

if (common.no_of_pending_actions >= MAX_PENDING_ACTIONS) {
  return false;
  }
common.pending_action[common.no_of_pending_actions].status=actual_status;
common.pending_action[common.no_of_pending_actions].action=action;
common.pending_action[common.no_of_pending_actions].sub_selection=sub_selection;
common.no_of_pending_actions++;
return true;
}

bool handle_execution_result(struct status_struct *actual_status,
                             bool execution_result)
{
int i;
unsigned int old_flags;
_kernel_oserror *error_os;

/* perform all necassary updates inside window */
/* option buttons */
if ((actual_status->information.update_information & UPDATE_ERROR_STATUS) != 0) {
  if ((actual_status->information.general_variables.error_status & 0x00000008) == 0) {
    if ((error_os=button_set_value(0,
                                   actual_status->window,
                                   APP_GAGDET_ERROR_INDICATOR,
                                   "no")) != NULL) application_report_error(error_os, true);
    }
  else {
    if ((error_os=button_set_value(0,
                                   actual_status->window,
                                   APP_GAGDET_ERROR_INDICATOR,
                                   "yes")) != NULL) application_report_error(error_os, true);
    }
  if ((actual_status->information.general_variables.error_status & 0x00000010) == 0) {
    if ((error_os=button_set_value(0,
                                   actual_status->window,
                                   APP_GAGDET_SELECT_INDICATOR,
                                   "no")) != NULL) application_report_error(error_os, true);
    }
  else {
    if ((error_os=button_set_value(0,
                                   actual_status->window,
                                   APP_GAGDET_SELECT_INDICATOR,
                                   "yes")) != NULL) application_report_error(error_os, true);
    }
  if ((actual_status->information.general_variables.error_status & 0x00000020) != 0) {
    if ((error_os=button_set_value(0,
                                   actual_status->window,
                                   APP_GAGDET_PAPER_INDICATOR,
                                   "no")) != NULL) application_report_error(error_os, true);
    }
  else {
    if ((error_os=button_set_value(0,
                                   actual_status->window,
                                   APP_GAGDET_PAPER_INDICATOR,
                                   "yes")) != NULL) application_report_error(error_os, true);
    }
  }
/* message */
if ((actual_status->information.update_information & UPDATE_MESSAGE) != 0) {
  if ((error_os=displayfield_set_value(0,
                                       actual_status->window,
                                       APP_GAGDET_MESSAGE,
                                       actual_status->information.general_variables.message)) != NULL) application_report_error(error_os, true);
  }
/* Drawing */
if ((actual_status->information.update_information & UPDATE_DISPLAY) != 0) {
  BBox redraw_area;

  if ((error_os=gadget_get_bbox(0,
                                actual_status->window,
                                APP_GAGDET_DRAW_BOX,
                                &redraw_area)) != NULL) application_report_error(error_os, true);
  if ((error_os=window_force_redraw(0,
                                    actual_status->window,
                                    &redraw_area)) != NULL) application_report_error(error_os, true);
  }
actual_status->information.update_information=UPDATE_NO_UPDATES;
/* check for errors */
if (execution_result) return true;
if (actual_status->information.dialogue_flag) {
  if (strlen(actual_status->information.general_variables.dialog_button[2]) > 0) {
    if ((error_os=gadget_get_flags(0,
                                   actual_status->window,
                                   APP_GAGDET_DIALOGUE_BUTTON1,
                                   &old_flags)) != NULL) application_report_error(error_os, true);
    if ((error_os=gadget_set_flags(0,
                                   actual_status->window,
                                   APP_GAGDET_DIALOGUE_BUTTON1,
                                   old_flags & 0x7FFFFFFF)) != NULL) application_report_error(error_os, true);
    if ((error_os=actionbutton_set_text(0,
                                        actual_status->window,
                                        APP_GAGDET_DIALOGUE_BUTTON1,
                                        actual_status->information.general_variables.dialog_button[0])) != NULL) application_report_error(error_os, true);
    if ((error_os=gadget_get_flags(0,
                                   actual_status->window,
                                   APP_GAGDET_DIALOGUE_BUTTON2,
                                   &old_flags)) != NULL) application_report_error(error_os, true);
    if ((error_os=gadget_set_flags(0,
                                   actual_status->window,
                                   APP_GAGDET_DIALOGUE_BUTTON2,
                                   old_flags & 0x7FFFFFFF)) != NULL) application_report_error(error_os, true);
    if ((error_os=actionbutton_set_text(0,
                                        actual_status->window,
                                        APP_GAGDET_DIALOGUE_BUTTON2,
                                        actual_status->information.general_variables.dialog_button[1])) != NULL) application_report_error(error_os, true);
    if ((error_os=gadget_get_flags(0,
                                   actual_status->window,
                                   APP_GAGDET_DIALOGUE_BUTTON3,
                                   &old_flags)) != NULL) application_report_error(error_os, true);
    if ((error_os=gadget_set_flags(0,
                                   actual_status->window,
                                   APP_GAGDET_DIALOGUE_BUTTON3,
                                   old_flags & 0x7FFFFFFF)) != NULL) application_report_error(error_os, true);
    if ((error_os=actionbutton_set_text(0,
                                        actual_status->window,
                                        APP_GAGDET_DIALOGUE_BUTTON3,
                                        actual_status->information.general_variables.dialog_button[2])) != NULL) application_report_error(error_os, true);
    }
  else if (strlen(actual_status->information.general_variables.dialog_button[1]) > 0) {
    if ((error_os=gadget_get_flags(0,
                                   actual_status->window,
                                   APP_GAGDET_DIALOGUE_BUTTON1,
                                   &old_flags)) != NULL) application_report_error(error_os, true);
    if ((error_os=gadget_set_flags(0,
                                   actual_status->window,
                                   APP_GAGDET_DIALOGUE_BUTTON1,
                                   old_flags & 0x7FFFFFFF)) != NULL) application_report_error(error_os, true);
    if ((error_os=actionbutton_set_text(0,
                                        actual_status->window,
                                        APP_GAGDET_DIALOGUE_BUTTON1,
                                        actual_status->information.general_variables.dialog_button[0])) != NULL) application_report_error(error_os, true);
    if ((error_os=gadget_get_flags(0,
                                   actual_status->window,
                                   APP_GAGDET_DIALOGUE_BUTTON3,
                                   &old_flags)) != NULL) application_report_error(error_os, true);
    if ((error_os=gadget_set_flags(0,
                                   actual_status->window,
                                   APP_GAGDET_DIALOGUE_BUTTON3,
                                   old_flags & 0x7FFFFFFF)) != NULL) application_report_error(error_os, true);
    if ((error_os=actionbutton_set_text(0,
                                        actual_status->window,
                                        APP_GAGDET_DIALOGUE_BUTTON3,
                                        actual_status->information.general_variables.dialog_button[1])) != NULL) application_report_error(error_os, true);
    }
  else if (strlen(actual_status->information.general_variables.dialog_button[0]) > 0) {
    if ((error_os=gadget_get_flags(0,
                                   actual_status->window,
                                   APP_GAGDET_DIALOGUE_BUTTON2,
                                   &old_flags)) != NULL) application_report_error(error_os, true);
    if ((error_os=gadget_set_flags(0,
                                   actual_status->window,
                                   APP_GAGDET_DIALOGUE_BUTTON2,
                                   old_flags & 0x7FFFFFFF)) != NULL) application_report_error(error_os, true);
    if ((error_os=actionbutton_set_text(0,
                                        actual_status->window,
                                        APP_GAGDET_DIALOGUE_BUTTON2,
                                        actual_status->information.general_variables.dialog_button[0])) != NULL) application_report_error(error_os, true);
    }
  else {
    show_message(ERROR_NO_DIALOGUE_BUTTON_SET,
                 actual_status->information.trace);
    return false;
    }
  if (strlen(actual_status->information.general_variables.dialog_message) > 0) {
    if ((error_os=gadget_get_flags(0,
                                   actual_status->window,
                                   APP_GAGDET_DIALOGUE_MESSAGE,
                                   &old_flags)) != NULL) application_report_error(error_os, true);
    if ((error_os=gadget_set_flags(0,
                                   actual_status->window,
                                   APP_GAGDET_DIALOGUE_MESSAGE,
                                   old_flags & 0x7FFFFFFF)) != NULL) application_report_error(error_os, true);
    if ((error_os=displayfield_set_value(0,
                                         actual_status->window,
                                         APP_GAGDET_DIALOGUE_MESSAGE,
                                         actual_status->information.general_variables.dialog_message)) != NULL) application_report_error(error_os, true);
    }
  /* in case menu is still open so close it */
  if ((error_os=toolbox_hide_object(0,
                                   actual_status->main_menu)) != NULL) application_report_error(error_os, true);
  return true;
  }
else {
  /* Build an error message */
  for (i=actual_status->information.error.number_of_parameters; i < MAX_ERROR_PARAMETERS; i++) {
    strcpy(actual_status->information.error.parameter[i], "");
    }
  show_message(actual_status->information.error.number,
               actual_status->information.trace,
               actual_status->information.error.parameter[0],
               actual_status->information.error.parameter[1],
               actual_status->information.error.parameter[2]);
  if (actual_status->information.error.number == ERROR_WRONG_CALL) {
    drop_application();
    exit(EXIT_FAILURE);
    }
  actual_status->information.error.number=ERROR_NO_ERROR;
  return false;
  }
}

bool control_action_execution(struct status_struct *actual_status,
                              int action,
                              int sub_selection)
{

/* perform action */
return handle_execution_result(actual_status,
                               do_action(&actual_status->information,
                                         action,
                                         sub_selection));
}

void enable_window_input(struct status_struct *actual_status)
{
_kernel_oserror *error_os;

if (actual_status->lock_input) {
  actual_status->lock_input=false;
  if ((error_os=window_set_menu(0,
                                actual_status->window,
                                actual_status->main_menu)) != NULL) application_report_error(error_os, true);
  if ((error_os=window_set_pointer(0,
                                   actual_status->window,
                                   NULL,
                                   0,
                                   0)) != NULL) application_report_error(error_os, true);
  }
}

void disable_window_input(struct status_struct *actual_status)
{
_kernel_oserror *error_os;

if (!actual_status->lock_input) {
  actual_status->lock_input=true;
  if ((error_os=window_set_menu(0,
                                actual_status->window,
                                0)) != NULL) application_report_error(error_os, true);
  if ((error_os=window_set_pointer(0,
                                   actual_status->window,
                                   "ptr_busy",
                                   0,
                                   0)) != NULL) application_report_error(error_os, true);
  }
}

/* ---------- Redraw handling --------- */
int redraw_status(int event_code,
                  WimpPollBlock *event,
                  IdBlock *id_block,
                  void *client_handle)
{
int i;
int loop_flag;
struct status_struct *actual_status;
_kernel_oserror *error_os;
WimpGetWindowStateBlock state;
WimpRedrawWindowBlock block;
BBox window_extent, labelled_box_extent;

actual_status=client_handle;
/* Taken from Castles Hyper Example */
state.window_handle = event->redraw_window_request.window_handle;
block.window_handle = event->redraw_window_request.window_handle;
wimp_get_window_state(&state);
if ((error_os=window_get_extent(0,
                                actual_status->window,
                                &window_extent)) != NULL) application_report_error(error_os, false);
if ((error_os=gadget_get_bbox(0,
                              actual_status->window,
                              APP_GAGDET_DRAW_BOX,
                              &labelled_box_extent)) != NULL) application_report_error(error_os, false);
wimp_redraw_window(&block,
                   &loop_flag);
for (i=0; i < MAX_OVERLAYS; i++) {
  actual_status->information.loaded_file[i].transformation[2][0]=(state.visible_area.xmin + labelled_box_extent.xmin - state.xscroll) * 256;
  actual_status->information.loaded_file[i].transformation[2][1]=(state.visible_area.ymax + (labelled_box_extent.ymin - window_extent.ymin) - (window_extent.ymax - window_extent.ymin) - state.yscroll) * 256;
  }
while(loop_flag)  {
  for (i=0; i < MAX_OVERLAYS; i++) {
    if (actual_status->information.loaded_file[i].file.data) {
       drawfile_render(0,
                       actual_status->information.loaded_file[i].file.data,
                       actual_status->information.loaded_file[i].file.length,
                       &actual_status->information.loaded_file[i].transformation,
                       &(block.redraw_area),
                       0);
       }
    }
  wimp_get_rectangle(&block,
                     &loop_flag);
  }
return EVENT_CLAIMED;
}

/* ---------- General initialization and dropping --------- */
extern int close_status_window(int event_code, ToolboxEvent *event, IdBlock *id_block, void *client_handle);

bool drop_status(struct status_struct **first_status,
                 struct status_struct *status)
{
_kernel_oserror *error_os;

if ((!first_status) || (!status)) return false;
if (status->previous_status) {
  status->previous_status->next_status=status->next_status;
  }
else {
  *first_status=status->next_status;
  }
if (status->next_status) {
  status->next_status->previous_status=status->previous_status;
  }
/* Attach menu etc if removed to delete automatically */
enable_window_input(status);
/* Status window no longer needed */
if (status->window) {
  if ((error_os=event_deregister_wimp_handler(status->window,
                                              Wimp_ERedrawWindow,
                                              redraw_status,
                                              status)) != NULL) application_report_error(error_os, false);
  if ((error_os=event_deregister_toolbox_handler(status->window,
                                                 Window_HasBeenHidden,
                                                 close_status_window,
                                                 status)) != NULL) application_report_error(error_os, false);
  if ((error_os=toolbox_delete_object(0,
                                      status->window)) != NULL) application_report_error(error_os, false);
  }
drop_information(&status->information);
free(status);
return true;
}

bool initialize_application(void)
{
struct settings_struct settings;
_kernel_swi_regs regs;

common.first_status=NULL;
common.shutdown_flag=false;
common.no_of_pending_actions=0;
common.trace_on=false;
_kernel_swi(OS_ReadMonotonicTime, &regs, &regs);
common.last_activity_time=(unsigned long) regs.r[0];
read_settings(&settings);
printer_initialize();
network_initialize(settings.network,
                   settings.netmask,
                   settings.port,
                   printer_network_request,
                   settings.trace_file_name);
return true;
}

bool drop_application(void)
{

while (common.first_status) {
  drop_status(&common.first_status,
              common.first_status);
  }
network_shutdown();
printer_shutdown();
return true;
}

/* ---------- Toolbox handling --------- */
int status_window_button_click_handler(int event_code,
                                       ToolboxEvent *event,
                                       IdBlock *id_block,
                                       void *client_handle)
{
int i;
unsigned int old_flags;
struct status_struct *actual_status;
_kernel_oserror *error_os;

/* Client handle points to required memory information */
actual_status=(struct status_struct *) client_handle;
/* Clear and disable message field and buttons */
/* Clear variable values */
strcpy(actual_status->information.general_variables.dialog_message, "");
for (i=0; i < MAX_BUTTONS; i++) {
  strcpy(actual_status->information.general_variables.dialog_button[i], "");
  }
/* Fade dialogue message */
if ((error_os=gadget_get_flags(0,
                               id_block->self_id,
                               APP_GAGDET_DIALOGUE_MESSAGE,
                               &old_flags)) != NULL) application_report_error(error_os, true);
if ((error_os=gadget_set_flags(0,
                               id_block->self_id,
                               APP_GAGDET_DIALOGUE_MESSAGE,
                               old_flags | 0x80000000)) != NULL) application_report_error(error_os, true);
if ((error_os=displayfield_set_value(0,
                                     id_block->self_id,
                                     APP_GAGDET_DIALOGUE_MESSAGE,
                                     "")) != NULL) application_report_error(error_os, true);
for (i=0; i < MAX_BUTTONS; i++) {
  /* Fade button */
  if ((error_os=gadget_get_flags(0,
                                 id_block->self_id,
                                 i + APP_GAGDET_DIALOGUE_BUTTON1,
                                 &old_flags)) != NULL) application_report_error(error_os, true);
  if ((error_os=gadget_set_flags(0,
                                 id_block->self_id,
                                 i + APP_GAGDET_DIALOGUE_BUTTON1,
                                 old_flags | 0x80000000)) != NULL) application_report_error(error_os, true);
  /* No text inside button */
  if ((error_os=actionbutton_set_text(0,
                                       id_block->self_id,
                                       i + APP_GAGDET_DIALOGUE_BUTTON1,
                                       "")) != NULL) application_report_error(error_os, true);
  }
/* store result */
actual_status->information.general_variables.dialog_result=1<<(id_block->self_component - APP_GAGDET_DIALOGUE_BUTTON1);
/* continue action */
handle_execution_result(actual_status,
                        continue_action(&actual_status->information));
return EVENT_CLAIMED;
}

int cartridge_manufacturer_menu_click_handler(int event_code,
                                              ToolboxEvent *event,
                                              IdBlock *id_block,
                                              void *client_handle)
{
char menu_cartridge_manufacturer[MAX_MESSAGE_LENGTH];
int bytes_transferred;
struct status_struct *actual_status;
_kernel_oserror *error_os;

/* Client handle points to required memory information */
actual_status=(struct status_struct *) client_handle;
if ((error_os=menu_set_tick(0,
                            id_block->self_id,
                            actual_status->actual_cartridge_manufacturer,
                            0)) != NULL) application_report_error(error_os, true);
if ((error_os=menu_get_entry_text(0,
                                  id_block->self_id,
                                  id_block->self_component,
                                  menu_cartridge_manufacturer,
                                  MAX_MESSAGE_LENGTH-1,
                                  &bytes_transferred)) != NULL) application_report_error(error_os, true);
actual_status->actual_cartridge_manufacturer=id_block->self_component;
if ((error_os=menu_set_tick(0,
                            id_block->self_id,
                            actual_status->actual_cartridge_manufacturer,
                            1)) != NULL) application_report_error(error_os, true);
/* Set all entries accordingly */
set_cartridge_info(&actual_status->information.general_variables,
                  menu_cartridge_manufacturer);
return EVENT_CLAIMED;
}

int cleaning_level_menu_click_handler(int event_code,
                                      ToolboxEvent *event,
                                      IdBlock *id_block,
                                      void *client_handle)
{
struct status_struct *actual_status;
_kernel_oserror *error_os;

/* Client handle points to required memory information */
actual_status=(struct status_struct *) client_handle;
if ((error_os=menu_set_tick(0,
                            id_block->self_id,
                            actual_status->information.general_variables.cleaning_level - 1,
                            0)) != NULL) application_report_error(error_os, true);
actual_status->information.general_variables.cleaning_level=id_block->self_component + 1;
if ((error_os=menu_set_tick(0,
                            id_block->self_id,
                            actual_status->information.general_variables.cleaning_level - 1,
                            1)) != NULL) application_report_error(error_os, true);
return EVENT_CLAIMED;
}

int change_cartridge_menu_click_handler(int event_code,
                                        ToolboxEvent *event,
                                        IdBlock *id_block,
                                        void *client_handle)
{

if (id_block->self_component <= MAX_CARTRIDGE) {
  /* Client handle points to required memory information */
  register_action(client_handle,
                  ACTION_CODE_CHANGE_CARTRIDGE,
                  id_block->self_component);
  disable_window_input(client_handle);
  }
return EVENT_CLAIMED;
}

int clean_head_menu_click_handler(int event_code,
                                  ToolboxEvent *event,
                                  IdBlock *id_block,
                                  void *client_handle)
{

if (id_block->self_component <= MAX_CARTRIDGE) {
  /* Client handle points to required memory information */
  register_action(client_handle,
                  ACTION_CODE_CLEAN_HEAD,
                  id_block->self_component);
  disable_window_input(client_handle);
  }
return EVENT_CLAIMED;
}

int head_calibration_menu_click_handler(int event_code,
                                        ToolboxEvent *event,
                                        IdBlock *id_block,
                                        void *client_handle)
{

if (id_block->self_component <= MAX_CARTRIDGE) {
  /* Client handle points to required memory information */
  register_action(client_handle,
                  ACTION_CODE_CALIBRATE_HEAD,
                  id_block->self_component);
  disable_window_input(client_handle);
  }
return EVENT_CLAIMED;
}

int change_head_menu_click_handler(int event_code,
                                   ToolboxEvent *event,
                                   IdBlock *id_block,
                                   void *client_handle)
{

if (id_block->self_component <= MAX_CARTRIDGE) {
  /* Client handle points to required memory information */
  register_action(client_handle,
                  ACTION_CODE_CHANGE_HEAD,
                  id_block->self_component);
  disable_window_input(client_handle);
  }
return EVENT_CLAIMED;
}

int main_menu_click_handler(int event_code,
                            ToolboxEvent *event,
                            IdBlock *id_block,
                            void *client_handle)
{
_kernel_oserror *error_os;
ObjectId sub_menu;

/* Filter clicks on entries with sub menus */
if ((error_os=menu_get_sub_menu_show(0,
                                     id_block->self_id,
                                     id_block->self_component,
                                     &sub_menu)) != NULL) application_report_error(error_os, true);
if ((id_block->self_component <= MAX_CARTRIDGE) &&
    (sub_menu == 0)) {
  /* Client handle points to required memory information */
  register_action(client_handle,
                  id_block->self_component,
                  -1);
  disable_window_input(client_handle);
  }
return EVENT_CLAIMED;
}

void menue_fade_handler(ObjectId menu_id,
                        unsigned long *fade_pattern,
                        int pattern_size,
                        int fade_type)
{
int i,j;
_kernel_oserror *error_os;

for (i=0; i < pattern_size; i++) {
  for (j=0; j <= MAX_USER_OPERATION; j++) {
    if ((fade_pattern[i] & (1<<j)) != 0) {
      if ((error_os=menu_set_fade(0,
                                  menu_id,
                                  (i*32) + j,
                                  fade_type)) != NULL) application_report_error(error_os, true);
      }
    }
  }
}

int main_menu_open_handler(int event_code,
                           ToolboxEvent *event,
                           IdBlock *id_block,
                           void *client_handle)
{
struct status_struct *actual_status;
_kernel_oserror *error_os;

/* Client handle points to required memory information */
actual_status=(struct status_struct *) client_handle;
if (actual_status->information.dialogue_flag) {
  menue_fade_handler(id_block->self_id,
                     &actual_status->information.available_actions,
                     1,
                     1);
  }
else {
  menue_fade_handler(id_block->self_id,
                     &actual_status->information.available_actions,
                     1,
                     0);
  }
if (actual_status->component_counter > 0) {
  if ((error_os=menu_set_fade(0,
                              id_block->self_id,
                              APP_MENU_CARTRIDGE_MANUFACTURERS,
                              0)) != NULL) application_report_error(error_os, true);
  }
else {
  if ((error_os=menu_set_fade(0,
                              id_block->self_id,
                              APP_MENU_CARTRIDGE_MANUFACTURERS,
                              1)) != NULL) application_report_error(error_os, true);
  }
if (actual_status->information.available_cleaning_levels != 0) {
  if ((error_os=menu_set_fade(0,
                              id_block->self_id,
                              APP_MENU_CLEANING_LEVELS,
                              0)) != NULL) application_report_error(error_os, true);
  }
else {
  if ((error_os=menu_set_fade(0,
                              id_block->self_id,
                              APP_MENU_CLEANING_LEVELS,
                              1)) != NULL) application_report_error(error_os, true);
  }
return EVENT_CLAIMED;
}

int evaluate_new_toolbox_object(int event_code,
                                ToolboxEvent *event,
                                IdBlock *id_block,
                                void *client_handle)
{
_kernel_oserror *error_os;
ToolboxObjectAutoCreatedEvent *actual_event;
struct status_struct *actual_status;

/* Client handle points to required memory information */
actual_status=(struct status_struct *) client_handle;
actual_event=(ToolboxObjectAutoCreatedEvent *) event;
if (strcmp(actual_event->template_name, "PrintAction") == 0) {
  if ((error_os=event_register_toolbox_handler(id_block->self_id,
                                               Menu_AboutToBeShown,
                                               main_menu_open_handler,
                                               client_handle)) != NULL) application_report_error(error_os, true);
  if ((error_os=event_register_toolbox_handler(id_block->self_id,
                                               Menu_Selection,
                                               main_menu_click_handler,
                                               client_handle)) != NULL) application_report_error(error_os, true);
  /* Created as last object. The handler can be deregistered now. */
  if ((error_os=event_deregister_toolbox_handler(-1,
                                                 Toolbox_ObjectAutoCreated,
                                                 evaluate_new_toolbox_object,
                                                 client_handle)) != NULL) application_report_error(error_os, true);
  /* Store ID for various access purposes */
  actual_status->main_menu=id_block->self_id;
  }
else if (strcmp(actual_event->template_name, "ChgCatr") == 0) {
  menue_fade_handler(id_block->self_id,
                     actual_status->information.available_cartridge_change,
                     (MAX_CARTRIDGE/32)+1,
                     0);
  if ((error_os=event_register_toolbox_handler(id_block->self_id,
                                               Menu_Selection,
                                               change_cartridge_menu_click_handler,
                                               client_handle)) != NULL) application_report_error(error_os, true);
  }
else if (strcmp(actual_event->template_name, "CleanHead") == 0) {
  menue_fade_handler(id_block->self_id,
                     actual_status->information.available_clean_head,
                     (MAX_CARTRIDGE/32)+1,
                     0);
  if ((error_os=event_register_toolbox_handler(id_block->self_id,
                                               Menu_Selection,
                                               clean_head_menu_click_handler,
                                               client_handle)) != NULL) application_report_error(error_os, true);
  }
else if (strcmp(actual_event->template_name, "HeadCalib") == 0) {
  menue_fade_handler(id_block->self_id,
                     actual_status->information.available_calibrate_head,
                     (MAX_CARTRIDGE/32)+1,
                     0);
  if ((error_os=event_register_toolbox_handler(id_block->self_id,
                                               Menu_Selection,
                                               head_calibration_menu_click_handler,
                                               client_handle)) != NULL) application_report_error(error_os, true);
  }
else if (strcmp(actual_event->template_name, "ChgHead") == 0) {
  menue_fade_handler(id_block->self_id,
                     actual_status->information.available_head_change,
                     (MAX_CARTRIDGE/32)+1,
                     0);
  if ((error_os=event_register_toolbox_handler(id_block->self_id,
                                               Menu_Selection,
                                               change_head_menu_click_handler,
                                               client_handle)) != NULL) application_report_error(error_os, true);
  }
else if (strcmp(actual_event->template_name, "CatrManu") == 0) {
  int i;

   /* Modify used menu entries */
  for (i=0; i < actual_status->component_counter; i++) {
    if ((error_os=menu_set_entry_text(0,
                                      id_block->self_id,
                                      i,
                                      actual_status->cartridge_manufacturer[i])) != NULL) {
      application_report_error(error_os, true);
      }
    }
  /* Delete all unused menu entries */
  for (i=9; i >= actual_status->component_counter; i--) {
    if ((error_os=menu_remove_entry(0,
                                    id_block->self_id,
                                    i)) != NULL) application_report_error(error_os, true);
    }
  if (actual_status->component_counter > 0) {
    if ((error_os=event_register_toolbox_handler(id_block->self_id,
                                                 Menu_Selection,
                                                 cartridge_manufacturer_menu_click_handler,
                                                 client_handle)) != NULL) application_report_error(error_os, true);
    }
  }
else if (strcmp(actual_event->template_name, "ClnHeadLvl") == 0) {
  /* Tick actual level */
  if (actual_status->information.general_variables.cleaning_level > 0) {
    if ((error_os=menu_set_tick(0,
                                id_block->self_id,
                                actual_status->information.general_variables.cleaning_level - 1,
                                1)) != NULL) application_report_error(error_os, true);
    }
  menue_fade_handler(id_block->self_id,
                     &actual_status->information.available_cleaning_levels,
                     1,
                     0);
  if ((error_os=event_register_toolbox_handler(id_block->self_id,
                                               Menu_Selection,
                                               cleaning_level_menu_click_handler,
                                               client_handle)) != NULL) application_report_error(error_os, true);
  }
return EVENT_NOT_CLAIMED;
}

/* !!!!!!!!!! functions !!!!!!!!!! */
/* ---------- Application Handling --------- */
int program_quitT(int event_code,
                  ToolboxEvent *event,
                  IdBlock *id_block,
                  void *client_handle)
{

common.shutdown_flag=true;
return EVENT_CLAIMED;
}

int close_status_window(int event_code,
                        ToolboxEvent *event,
                        IdBlock *id_block,
                        void *client_handle)
{
struct status_struct *actual_status;

actual_status=client_handle;
drop_status(&common.first_status,
            actual_status);
return EVENT_CLAIMED;
}

int show_status_window(int event_code,
                       ToolboxEvent *event,
                       IdBlock *id_block,
                       void *client_handle)
{
struct status_struct *actual_status;

/* Generate new status */
if (!(actual_status=malloc(sizeof(struct status_struct)))) {
  show_message(ERROR_MEMORY_ALLOCATION_WINDOW,
               NULL);
  return EVENT_CLAIMED;
  }
actual_status->window=0;
actual_status->next_status=common.first_status;
actual_status->previous_status=NULL;
actual_status->lock_input=false;
common.first_status=actual_status;
if (actual_status->next_status) {
  actual_status->next_status->previous_status=actual_status;
  }
initialize_information(&actual_status->information);
/* postphone remaining part of the operation for
   it may contain network activities which are requiring
   an additional poll which should not be done inside
   a toolbox call itself */
register_action(actual_status,
                ACTION_CODE_NEW_WINDOW,
                0);
return EVENT_CLAIMED;
}

int show_status_window_internal(struct status_struct *actual_status)
{
char *c;
char temp_str[MAX_STRING_LENGTH];
char actual_manufacturer[MAX_MESSAGE_LENGTH];
char actual_printer_type[MAX_MESSAGE_LENGTH];
char actual_cartridge_manufacturer[MAX_MESSAGE_LENGTH];
int i;
int actual_cartridge;
int territory, actual_territory;
bool loop_flag;
FILE *info_file;
_kernel_oserror *error_os;
struct status_struct *temp_status;
unsigned long actual_printers_printer;

/* Check for trace request */
if (common.trace_on) {
  char time_string[MAX_STRING_LENGTH];
  time_t now;

  time(&now);
  strftime(time_string,
           MAX_STRING_LENGTH,
           "%H_%M_%S",
           localtime(&now));
  sprintf(temp_str,
          "%s.Trace%s",
          TRACE_PATH,
          time_string);
  if ((actual_status->information.trace=fopen(temp_str, "w")) == NULL) {
    show_message(ERROR_CANT_OPEN_TRACE_FILE,
                 actual_status->information.trace,
                 temp_str);
    }
  }
/* Get actual printer name */
if ((actual_printers_printer=determine_actual_printer()) != PRINTER_ICON_HANDLE_UNKNOWN) {
  if ((actual_status->information.printer=activate_printer(actual_printers_printer)) == NULL) {
    show_message(ERROR_PRINTER_DETERMINATION,
                 actual_status->information.trace);
    drop_status(&common.first_status,
                actual_status);
    return EVENT_CLAIMED;
    }
  if (actual_status->information.trace) {
    fprintf(actual_status->information.trace,
            "Printer Name: %s\n",
            actual_status->information.printer->printer_name);
    fprintf(actual_status->information.trace,
            "Printer$Path: %s\n",
            actual_status->information.printer->connection_name);
    }
  if (!determine_connection(actual_status->information.printer,
                            &(actual_status->information.error),
                            actual_status->information.general_variables.interface,
                            actual_status->information.general_variables.protocol)) {
    for (i=actual_status->information.error.number_of_parameters; i < MAX_ERROR_PARAMETERS; i++) {
      strcpy(actual_status->information.error.parameter[i], "");
      }
    show_message(actual_status->information.error.number,
                 actual_status->information.trace,
                 actual_status->information.error.parameter[0],
                 actual_status->information.error.parameter[1],
                 actual_status->information.error.parameter[2]);
    drop_status(&common.first_status,
                actual_status);
    return EVENT_CLAIMED;
    }
  if (actual_status->information.trace) {
    fprintf(actual_status->information.trace,
            "Connection type: %d I: %s P: %s\n",
            actual_status->information.printer->connection_type,
            actual_status->information.general_variables.interface,
            actual_status->information.general_variables.protocol);
    }
  }
else {
  show_message(ERROR_PRINTER_DETERMINATION,
               actual_status->information.trace);
  drop_status(&common.first_status,
              actual_status);
  return EVENT_CLAIMED;
  }
/* Check whether a windows for the according printer has been
   already opened. Compare Printer name. */
temp_status=common.first_status;
while (temp_status) {
  if (temp_status != actual_status) {
    if (strcmp(temp_status->information.printer->printer_name, actual_status->information.printer->printer_name) == 0) {
      /* Ignore Click */
      if (actual_status->information.trace) {
        fprintf(actual_status->information.trace,
                "Windows already opened for the printer.\n");
        }
      drop_status(&common.first_status,
                  actual_status);
      return EVENT_CLAIMED;
      }
    }
  temp_status=temp_status->next_status;
  }
/* Determine Printer type */
loop_flag=true;
/* First look whether there is direct a entry according to
   the printer name */
sprintf(temp_str,
        "%s.PrtAlias",
        CHOICES_PATH);
if (!search_printer_alias_file(&actual_status->information,
                               temp_str,
                               &loop_flag)) {
  show_message(ERROR_PRINTER_ALIAS_FILE,
               actual_status->information.trace,
               temp_str);
  drop_status(&common.first_status,
              actual_status);
  return EVENT_CLAIMED;
  }
if (loop_flag) {
  sprintf(temp_str,
          "%s.PrtAlias",
          RESOURCES_PATH);
  if (!search_printer_alias_file(&actual_status->information,
                                 temp_str,
                                 &loop_flag)) {
    show_message(ERROR_PRINTER_ALIAS_FILE,
                 actual_status->information.trace,
                 temp_str);
    drop_status(&common.first_status,
                actual_status);
    return EVENT_CLAIMED;
    }
  }
if (!loop_flag) {
  if (actual_status->information.trace) {
    fprintf(actual_status->information.trace,
            "In file %s a matching alias entry has been found: %s,%s,%s\n",
            temp_str,
            actual_status->information.printer->printer_name,
            actual_status->information.general_variables.manufacturer,
            actual_status->information.general_variables.printer_type);
    }
  }
else {
  /* If nothing found until now try IEEE identification */
  if (!determine_printer_type(actual_status->information.printer,
                              actual_status->information.general_variables.manufacturer,
                              actual_status->information.general_variables.printer_type)) {
    show_message(ERROR_PRINTER_TYPE,
                 actual_status->information.trace);
    drop_status(&common.first_status,
                actual_status);
    return EVENT_CLAIMED;
    }
  else {
    if (actual_status->information.trace) {
      fprintf(actual_status->information.trace,
              "IEEE device identification\n");
      fprintf(actual_status->information.trace,
              "IEEE Manufacturer: %s\n",
              actual_status->information.general_variables.manufacturer);
      fprintf(actual_status->information.trace,
              "IEEE Printer Type: %s\n",
              actual_status->information.general_variables.printer_type);
      }
    }
  }
/* Look for another mapping */
sprintf(temp_str,
        "%s.TypeAlias",
        RESOURCES_PATH);
if (!(info_file=fopen(temp_str, "r"))) {
  show_message(ERROR_PRINTER_TYPE_ALIAS_FILE,
               actual_status->information.trace,
               temp_str);
  drop_status(&common.first_status,
              actual_status);
  return EVENT_CLAIMED;
  }
loop_flag=true;
while ((loop_flag) &&
       (!feof(info_file))) {
  strcpy(temp_str, "");
  fgets(temp_str, MAX_STRING_LENGTH - 1, info_file);
  if (!feof(info_file)) {
    c=&temp_str[strlen(temp_str) - 1];
    while ((c >= temp_str) &&
           ((*c == '\n') ||
            (isspace(*c)))) {
      *c='\0';
      c--;
      }
    if (temp_str[0] != '#') {
      /* No comment. Real data */
      if (sscanf(temp_str,
                 "%[^,],%[^,],%[^,],%[^,]",
                 actual_manufacturer,
                 actual_printer_type,
                 actual_status->information.used_manufacturer,
                 actual_status->information.used_printer_type) == 4) {
        if ((strcmp(actual_manufacturer, actual_status->information.general_variables.manufacturer) == 0) &&
            (strcmp(actual_printer_type, actual_status->information.general_variables.printer_type) == 0)) {
          if (actual_status->information.trace) {
            fprintf(actual_status->information.trace,
                    "Alias matching: %s\n",
                    temp_str);
            }
          loop_flag=false;
          }
        }
      }
    }
  }
fclose(info_file);
if (loop_flag) {
  /* No alias found so use printer manufacturer and type directly */
  strcpy(actual_status->information.used_manufacturer, actual_status->information.general_variables.manufacturer);
  strcpy(actual_status->information.used_printer_type, actual_status->information.general_variables.printer_type);
  }
if (actual_status->information.trace) {
  fprintf(actual_status->information.trace,
          "Printer Manufacturer: %s\n",
          actual_status->information.used_manufacturer);
  fprintf(actual_status->information.trace,
          "Printer Type: %s\n",
          actual_status->information.used_printer_type);
  }
/* Evaluate the according command file */
i=strlen(RESOURCES_PATH) +
  strlen(COMMANDS_SUBPATH) +
  strlen(actual_status->information.used_manufacturer) +
  strlen(actual_status->information.used_printer_type) + 4;
if (!(actual_status->information.name_of_control_file=malloc(i))) {
  show_message(ERROR_MEMORY_CONTROL_FILE_NAME,
               actual_status->information.trace,
               RESOURCES_PATH,
               COMMANDS_SUBPATH,
               actual_status->information.used_manufacturer,
               actual_status->information.used_printer_type);
  drop_status(&common.first_status,
              actual_status);
  return EVENT_CLAIMED;
  }
sprintf(actual_status->information.name_of_control_file,
        "%s%s.%s.%s",
        RESOURCES_PATH,
        COMMANDS_SUBPATH,
        actual_status->information.used_manufacturer,
        actual_status->information.used_printer_type);
if (!determine_commands(&actual_status->information)) {
  show_message(ERROR_CONTROL_FILE,
               actual_status->information.trace,
               actual_status->information.name_of_control_file);
  drop_status(&common.first_status,
              actual_status);
  return EVENT_CLAIMED;
  }
/* Evaluate cartridge information file */
actual_status->component_counter=0;
territory=atoi(getenv("Territory"));
if ((info_file=fopen("<PrtInfo$Dir>.Resources.CtrInfo", "r")) == NULL) {
  show_message(ERROR_CARTRIDGE_INFORMATION_FILE,
               actual_status->information.trace);
  drop_status(&common.first_status,
              actual_status);
  return EVENT_CLAIMED;
  }
else {
  while(!feof(info_file)) {
    if (get_line(info_file,
                 temp_str)) {
      strcpy(actual_cartridge_manufacturer, "");
      strcpy(actual_manufacturer, "");
      strcpy(actual_printer_type, "");
      actual_territory=-1;
      actual_cartridge=-1;
      sscanf(temp_str,
             "%[^,],%[^,],%x,%[^,],%d",
             actual_manufacturer,
             actual_printer_type,
             &actual_cartridge,
             actual_cartridge_manufacturer,
             &actual_territory);
      if ((strcmp(actual_status->information.general_variables.manufacturer, actual_manufacturer) == 0) &&
          (strcmp(actual_status->information.general_variables.printer_type, actual_printer_type) == 0) &&
          (strlen(actual_cartridge_manufacturer) > 0) &&
          (actual_cartridge >= MIN_COLOUR) &&
          (actual_cartridge <= MAX_CARTRIDGE)) {
        if (((actual_territory == territory) ||
             /* Default */
             (actual_territory == 0)) &&
            /* Not more than 10 cartridge manufacturers */
            (actual_status->component_counter < 10)) {
          /* Search all existing emtries for actual one */
          loop_flag=false;
          i=0;
          while ((i < actual_status->component_counter) &&
                 (!loop_flag)) {
            if (strcmp(actual_status->cartridge_manufacturer[i], actual_cartridge_manufacturer) == 0) {
              loop_flag=true;
              }
            i++;
            }
          if (!loop_flag) {
            strcpy(actual_status->cartridge_manufacturer[i], actual_cartridge_manufacturer);
            actual_status->component_counter++;
            }
          }
        }
      }
    }
  fclose(info_file);
  }
if (actual_status->component_counter > 0) {
  actual_status->actual_cartridge_manufacturer=0;
  /* Set all entries accordingly */
  set_cartridge_info(&actual_status->information.general_variables,
                     actual_status->cartridge_manufacturer[0]);
  }
/* Generate the status window */
if ((error_os=toolbox_create_object(0,
                                    "PrintStatus",
                                    &actual_status->window)) != NULL) application_report_error(error_os, true);
/* Set printer name as title */
if ((error_os=window_set_title(0,
                               actual_status->window,
                               actual_status->information.printer->printer_name)) != NULL) application_report_error(error_os, true);
/* Install handlers */
if ((error_os=event_register_wimp_handler(actual_status->window,
                                          Wimp_ERedrawWindow,
                                          redraw_status,
                                          actual_status)) != NULL) application_report_error(error_os, true);
if ((error_os=event_register_toolbox_handler(actual_status->window,
                                             Window_HasBeenHidden,
                                             close_status_window,
                                             actual_status)) != NULL) application_report_error(error_os, true);
if ((error_os=event_register_toolbox_handler(actual_status->window,
                                             ActionButton_Selected,
                                             status_window_button_click_handler,
                                             actual_status)) != NULL) application_report_error(error_os, true);
/* Enable commands, cartridges and heads.
   The objects are automatically created during the next poll.
   The handler is automatically deregistered after the creation.
   */
if ((error_os=event_register_toolbox_handler(-1,
                                             Toolbox_ObjectAutoCreated,
                                             evaluate_new_toolbox_object,
                                             actual_status)) != NULL) application_report_error(error_os, true);
/* Open the status window */
if ((error_os=toolbox_show_object(0,
                                  actual_status->window,
                                  0,
                                  NULL,
                                  0,
                                  0)) != NULL) application_report_error(error_os, true);
/* Perform Init action if available */
if ((actual_status->information.available_actions & (1<<ACTION_CODE_INIT)) != 0) {
  register_action(actual_status,
                  ACTION_CODE_INIT,
                  0);
  }
return EVENT_CLAIMED;
}

/* ---------- Message Handling --------- */
int program_quitM(WimpMessage *message,
                  void *client_handle)
{

common.shutdown_flag=true;
return EVENT_CLAIMED;
}

/* ---------- Menue Handling --------- */
int show_general_help(int event_code,
                      ToolboxEvent *event,
                      IdBlock *id_block,
                      void *client_handle)
{
_kernel_swi_regs regs;

regs.r[0]=(int) "<PrtInfo$Dir>.!Help";
_kernel_swi(Wimp_StartTask, &regs, &regs);
return EVENT_CLAIMED;
}

int toggle_trace(int event_code,
                 ToolboxEvent *event,
                 IdBlock *id_block,
                 void *client_handle)
{
int ticked;
_kernel_oserror *error_os;

if ((error_os=menu_get_tick(0,
                            id_block->self_id,
                            APP_MENU_TRACE_ACTIVE,
                            &ticked)) != NULL) application_report_error(error_os, true);
if (ticked == 0) {
  common.trace_on=true;
  ticked=1;
  }
else {
  common.trace_on=false;
  ticked=0;
  }
if ((error_os=menu_set_tick(0,
                            id_block->self_id,
                            APP_MENU_TRACE_ACTIVE,
                            ticked)) != NULL) application_report_error(error_os, true);
return EVENT_CLAIMED;
}

int show_trace_directory(int event_code,
                         ToolboxEvent *event,
                         IdBlock *id_block,
                         void *client_handle)
{
char command[MAX_STRING_LENGTH];

sprintf(command,
        "Filer_OpenDir %s",
        TRACE_PATH);
system(command);
return EVENT_CLAIMED;
}


int show_choices_directory(int event_code,
                           ToolboxEvent *event,
                           IdBlock *id_block,
                           void *client_handle)
{
char command[MAX_STRING_LENGTH];

sprintf(command,
        "Filer_OpenDir %s",
        CHOICES_PATH);
system(command);
return EVENT_CLAIMED;
}

void my_poll(unsigned long poll_mask)
{
int event_code;
_kernel_swi_regs regs;
_kernel_oserror *error_os;
unsigned long min_time;
WimpPollBlock poll_block;

/* Determine polling time */
_kernel_swi(OS_ReadMonotonicTime, &regs, &regs);
if (((unsigned long) regs.r[0]) < (common.last_activity_time + 100)) {
  /* Short intervalls if something is going on */
  min_time=(unsigned long) regs.r[0] + 10;
  }
else if (((common.no_of_pending_actions > 0) &&
     ((poll_mask & POLL_ACTION) != 0)) ||
    (network_common.first_network_job &&
     ((poll_mask & POLL_NETWORK) != 0))) {
  /* reduce idle time if some activity is going on */
  min_time=(unsigned long) regs.r[0] + 50;
  }
else if ((network_common.socket != NO_SOCKET) &&
         ((poll_mask & POLL_NETWORK) != 0)) {
  /* reduce idle time if external network requests may occur */
  min_time=(unsigned long) regs.r[0] + 150;
  }
else {
  min_time=(unsigned long) regs.r[0] + 1000;
  }
event_code=0;
if ((error_os=event_poll_idle(&event_code,
                              &poll_block,
                              min_time,
                              NULL)) != NULL) application_report_error(error_os, true);
if ((poll_mask & POLL_ACTION) != 0) {
  if (common.no_of_pending_actions > 0) {
    common.no_of_pending_actions--;
    switch(common.pending_action[common.no_of_pending_actions].action) {
      case ACTION_CODE_NEW_WINDOW: {
        show_status_window_internal(common.pending_action[common.no_of_pending_actions].status);
        }
      break;
      default : {
        control_action_execution(common.pending_action[common.no_of_pending_actions].status,
                                 common.pending_action[common.no_of_pending_actions].action,
                                 common.pending_action[common.no_of_pending_actions].sub_selection);
        enable_window_input(common.pending_action[common.no_of_pending_actions].status);
        }
      }
    _kernel_swi(OS_ReadMonotonicTime, &regs, &regs);
    common.last_activity_time=(unsigned long) regs.r[0];
    }
  }
if ((poll_mask & POLL_NETWORK) != 0) {
  if (network_process()) {
    _kernel_swi(OS_ReadMonotonicTime, &regs, &regs);
    common.last_activity_time=(unsigned long) regs.r[0];
    }
  }
}

/* ---------- Main Loop --------- */
int main(int argc,
         char *argv[])
{
int toolbox_events=0,
    wimp_messages=0;
int task, wversion;
void *sprite_area;
_kernel_oserror *error_os;

/* General initializations */
if (!initialize_application()) {
  exit(EXIT_FAILURE);
  }
/* Register to Wimp/Toolbox */
if ((error_os=toolbox_initialise(0,
                                 WimpVersion,
                                 &wimp_messages,
                                 &toolbox_events,
                                 "<PrtInfo$Dir>",
                                 &messages,
                                 &id_block,
                                 &wversion,
                                 &task,
                                 &sprite_area)) != NULL) application_report_error(error_os, true);
if ((error_os=event_initialise(&id_block)) != NULL) application_report_error(error_os, true);
/* Null Events because Poll idle would fail else */
event_set_mask(0);
/* Installation of procedures to handle certain events */
if ((error_os=event_register_toolbox_handler(-1,
                                             TB_Quit,
                                             program_quitT,
                                             NULL)) != NULL) application_report_error(error_os, true);
if ((error_os=event_register_toolbox_handler(-1,
                                             Iconbar_Clicked,
                                             show_status_window,
                                             NULL)) != NULL) application_report_error(error_os, true);
if ((error_os=event_register_message_handler(Wimp_MQuit,
                                             program_quitM,
                                             NULL)) != NULL) application_report_error(error_os, true);
/* Installation of procedures to handle menue events */
if ((error_os=event_register_toolbox_handler(-1,
                                             APP_TBE_SHOW_GENERAL_HELP,
                                             show_general_help,
                                             NULL)) != NULL) application_report_error(error_os, true);
if ((error_os=event_register_toolbox_handler(-1,
                                             APP_TBE_TOGGLE_TRACE,
                                             toggle_trace,
                                             NULL)) != NULL) application_report_error(error_os, true);
if ((error_os=event_register_toolbox_handler(-1,
                                             APP_TBE_SHOW_TRACE,
                                             show_trace_directory,
                                             NULL)) != NULL) application_report_error(error_os, true);
if ((error_os=event_register_toolbox_handler(-1,
                                             APP_TBE_CHOICES,
                                             show_choices_directory,
                                             NULL)) != NULL) application_report_error(error_os, true);
/* Determine !Printers application handle */
if (!determine_printers_handle()) {
  show_message(ERROR_PRINTERS_NOT_RUNNING,
               false);
  drop_application();
  exit(EXIT_FAILURE);
  }
/* central loop */
while(!common.shutdown_flag) {
  my_poll(POLL_ALL);
  }
/* finish program */
drop_application();
exit(EXIT_SUCCESS);
}
